#ifndef PUDGE_GRFX_TEXTURE_HPP
#define PUDGE_GRFX_TEXTURE_HPP

namespace pudge { namespace grfx {

	struct CLAMP_TEXTURE
	{	
		static const GLenum glenum = GL_CLAMP; 
	};
	struct REPEAT_TEXTURE
	{	
		static const GLenum glenum = GL_REPEAT; 
	};

	template<class Traits> struct texture2d
	{
		typedef typename Traits::wrap_type wrap_type;
		typedef typename Traits::color_type color_type;

		GLuint id_;
		GLuint id() const
		{ 
			return id_; 
		}

		const GLuint width_;
		const GLuint height_;

		GLuint width() const
		{ 
			return width_; 
		}
		GLuint height() const
		{ 
			return height_; 
		}
		GLuint size() const
		{
			return width_ * height_;
		}

		texture2d(const GLuint w, const GLuint h, color_type * colors_) 
			: 	width_(w)
			,	height_(h)
		{
			const GLuint bytes = size() * sizeof(color_type);

			GLuint pbohandle, texhandle;
			glGenBuffers(1,&pbohandle);
			glGenTextures(1,&texhandle);

			id_ = texhandle;

			glBindTexture(GL_TEXTURE_2D, texhandle);
			glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbohandle);
			glBufferData(GL_PIXEL_UNPACK_BUFFER, bytes, (void*)colors_, GL_STATIC_DRAW);

			test_gl_error("texture cache");

			glTexImage2D
				(	GL_TEXTURE_2D
				,	0				// mipmap level
				,	GL_RGBA
				,	width_
				,	height_
				,	0
				,	Traits::color_type::format_type::glenum
				,	ogl_primitive<Traits::color_type::value_type>::glenum
				,	0 );

			test_gl_error("texture cache");

			glDeleteBuffers(1, &pbohandle);
			glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
			glBindTexture(GL_TEXTURE_2D, 0);

			test_gl_error("texture cache");
		}

		~texture2d()
		{
			glDeleteTextures(1, &id_);
			test_gl_error("texture decache");
		}
	};
}}

#endif